package net.deuce.perf;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.*;

public class ClientStats {
    private double successCount = 0;
    private double errorCount = 0;
    private double totalSuccessTime = 0;
    private double avgSuccessTime = 0;
    private long maxTime = 0;
    private long minTime = Long.MAX_VALUE;
    private Map<Double, Integer> thresholdResults = new HashMap<Double, Integer>();
    private List<Double> thresholds = new LinkedList<Double>();
    private Map<String, SimpleStats> breakdown = new HashMap<String, SimpleStats>();
    private Log log = LogFactory.getLog(getClass());

    public ClientStats(List<Double> thresholds) {
        //log.trace("");
        if (thresholds != null) {
            this.thresholds.addAll(thresholds);
        }
        for (Double d : thresholds) {
            thresholdResults.put(d, 0);
        }
    }

    public List<SimpleStats> getBreakdown() {
        //log.trace("");
        Set<SimpleStats> sortedSet = new TreeSet<SimpleStats>();
        return new LinkedList<SimpleStats>(new TreeSet<SimpleStats>(breakdown.values()));
    }

    private SimpleStats getSimpleStats(String label) {
        //log.trace("");
        SimpleStats ss = breakdown.get(label);
        if (ss == null) {
            ss = new SimpleStats(label);
            breakdown.put(label, ss);
        }
        return ss;
    }

    public Map<Double, Integer> getThresholdResults() {
        //log.trace("");
        return thresholdResults;
    }

    public Double getThresholdResult(Double d) {
        //log.trace("");
        double count = thresholdResults.get(d);
        if (successCount == 0) return 0.0;
        return count/successCount;
    }

    public Double getAvgResponseTime() {
        //log.trace("");
        if (successCount == 0) return 0.0;
        return totalSuccessTime/successCount;
    }

    public Double getErrorRate() {
        //log.trace("");
        if (successCount + errorCount == 0) return 0.0;
        return errorCount/(errorCount+successCount);
    }

    public void addSuccessTime(String label, long t) {
        //log.trace("");
        totalSuccessTime += t;
        successCount++;
        for (Double d : thresholds) {
            if (t <= d) {
                thresholdResults.put(d, thresholdResults.get(d)+1);
            }
        }
        if (t < minTime) {
            minTime = t;
        }
        if (t > maxTime) {
            maxTime = t;
        }
        SimpleStats ss = getSimpleStats(label);
        if (t < ss.getMinTime()) {
            ss.setMinTime(t);
        }
        if (t > ss.getMaxTime()) {
            ss.setMaxTime(t);
        }
        ss.addTime(t);
    }

    public long getMinTime() {
        //log.trace("");
        return minTime;
    }

    public long getMaxTime() {
        //log.trace("");
        return maxTime;
    }

    public void addError() {
        //log.trace("");
        errorCount++;
    }
}
